package com.plian.system.service.transfer.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.dao.bt.baseinfo.BaseInfoDao;
import com.plian.system.entity.fr.bulletin.BulletinValue;
import com.plian.system.entity.fr.bulletin.NewBulletin;
import com.plian.system.entity.sys.Org;
import com.plian.system.listener.NewBulletinEvent;
import com.plian.system.service.fr.bulletin.IBulletinValueService;
import com.plian.system.service.fr.bulletin.INewBulletinService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.sys.orgzation.OrgzationService;
import com.plian.system.service.transfer.IBulletinTransferService;
import com.plian.system.vo.fr.bulletin.BulletinTransferVO;
import com.plian.system.vo.fr.bulletin.BulletinTypeVO;
import com.plian.system.wrapper.fr.bulletin.NewBulletinWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.FormStatusConstant.FINISH;
import static com.plian.system.constant.sys.FormTypeConstant.FR_BULLETIN;

@Slf4j
@Service
@AllArgsConstructor
public class BulletinTransferServiceImpl implements IBulletinTransferService {

    private IOrgService orgService;

    private NewBulletinWrapper newBulletinWrapper;

    private INewBulletinService newBulletinService;

    private IBulletinValueService bulletinValueService;

    private ApplicationContext applicationContext;

    private OrgzationService orgzationService;

    private BaseInfoDao baseInfoDao;

    @Override
    public boolean submit(BulletinTransferVO bulletinTransferVO) {
        boolean result = false;
        try {
            NewBulletin oldBulletin = newBulletinService.getOne(new LambdaQueryWrapper<NewBulletin>()
                    .eq(NewBulletin::getDataSource, 1).eq(NewBulletin::getDataSourceId, bulletinTransferVO.getDataSourceId()));
            String id = UuidUtil.get32UUID();
            String year = DateUtil.format(bulletinTransferVO.getReportTime(), DateUtil.PATTERN_YEAR);
            List<BulletinTypeVO> typeVOS = baseInfoDao.findBulletin(year);
            Map<String, String> typeMap = typeVOS.stream().collect(Collectors.toMap(typeVO -> StringUtil.cleanChars(typeVO.getName()), BulletinTypeVO::getCode));
            List<BulletinValue> valueList = newBulletinService.getInitByYear(year, id);
            if (oldBulletin != null){
                valueList = bulletinValueService.list(new LambdaQueryWrapper<BulletinValue>()
                        .eq(BulletinValue::getBulletinId, oldBulletin.getId()));
                oldBulletin.setBulletinValues(valueList);
                id = oldBulletin.getId();
            }

            Org org = orgService.getOne(new LambdaQueryWrapper<Org>().eq(Org::getName, bulletinTransferVO.getOrgName()));
            NewBulletin newBulletin = newBulletinWrapper.transferToEntity(bulletinTransferVO);
            newBulletin.setOrgId(org.getId());
            newBulletin.setDataSource(TokenUtil.getTokenUserId());
            newBulletin.setStatus("" + FINISH);
            newBulletin.setReportTime(DateUtil.parse(DateUtil.format(bulletinTransferVO.getReportTime(), DateUtil.PATTERN_MONTH) + "-01", DateUtil.PATTERN_DATE));
            newBulletin.setFormType(String.valueOf(FR_BULLETIN));
            newBulletin.setId(id);

            List<PageData> parentList = new ArrayList<>();
            orgzationService.getParentList(org.getParentId(), parentList);
            int summaryCode = parentList.size();
            if ("6".equals(newBulletin.getTableTypeCode())){
                summaryCode = summaryCode - 1;
            }
            newBulletin.setSummaryCode(String.valueOf(summaryCode));

            if (CollectionUtil.isNotEmpty(bulletinTransferVO.getBulletinValues())){
                Map<String, BulletinValue> valueCodeMap = valueList.stream().collect(Collectors.toMap(BulletinValue::getTypeCode, value -> value));

                for (BulletinValue bulletinValue : bulletinTransferVO.getBulletinValues()){
                    bulletinValue.setBulletinId(id);
                    if (typeMap.containsKey(StringUtil.cleanChars(bulletinValue.getTypeName()))){
                        BulletinValue value = valueCodeMap.get(typeMap.get(StringUtil.cleanChars(bulletinValue.getTypeName())));
                        bulletinValue.setId(value.getId());
                        bulletinValue.setTypeCode(value.getTypeCode());
                        bulletinValue.setTypeName(value.getTypeName());
                        bulletinValue.setColumnName(value.getColumnName());
                        bulletinValue.setSortCode(value.getSortCode());
                        bulletinValue.setDisabled(value.getDisabled());
                    }
                }
            }
            newBulletin.setBulletinValues(bulletinTransferVO.getBulletinValues());

            result = newBulletinService.saveOrUpdate(newBulletin);
            bulletinValueService.remove(new LambdaQueryWrapper<BulletinValue>().eq(BulletinValue::getBulletinId, newBulletin.getId()));
            bulletinValueService.saveOrUpdateBatch(newBulletin.getBulletinValues());
            List<NewBulletin> list = new ArrayList<>();
            list.add(oldBulletin);
            list.add(newBulletin);
            applicationContext.publishEvent(new NewBulletinEvent(list));
        }catch (Exception e){
            log.error(ExceptionUtils.getFullStackTrace(e));
        }

        return result;
    }

    @Override
    public boolean submitList(List<BulletinTransferVO> bulletinTransferVOS) {
        boolean result = false;
        try {
            Set<Date> reportTimeSet = bulletinTransferVOS.stream().map(BulletinTransferVO::getReportTime).collect(Collectors.toSet());
            Set<String> reportTimeStrSet = reportTimeSet.stream()
                    .map(reportTime -> DateUtil.format(reportTime, DateUtil.PATTERN_MONTH)).collect(Collectors.toSet());
            String tokenUserId = TokenUtil.getTokenUserId();
            List<NewBulletin> oldBulletinList = newBulletinService.list(new LambdaQueryWrapper<NewBulletin>()
                    .apply(" date_format(report_time, '%Y-%m') in ('" + reportTimeStrSet.stream().collect(Collectors.joining("','")) + "')")
                    .eq(NewBulletin::getDataSource, tokenUserId));
            Map<String, NewBulletin> oldBulletinMap = oldBulletinList.stream().collect(Collectors.toMap(bulletin ->
                    DateUtil.format(bulletin.getReportTime(), DateUtil.PATTERN_MONTH)
                            + StringPool.UNDERSCORE + bulletin.getSummaryCode()
                            + StringPool.UNDERSCORE + bulletin.getOrgId(), bulletin -> bulletin ));
            List<Org> allOrg = orgService.getAllChild(TokenUtil.getTokenOrgId());
            Map<String, Org> orgNameMap = allOrg.stream().collect(Collectors.toMap(Org::getName, org -> org, (a,b) -> a));
            //暂时未考虑分公司情况
            for (BulletinTransferVO bulletinTransferVO : bulletinTransferVOS){
                String id = UuidUtil.get32UUID();
                String year = DateUtil.format(bulletinTransferVO.getReportTime(), DateUtil.PATTERN_YEAR);
                List<BulletinTypeVO> typeVOS = baseInfoDao.findBulletin(year);
                Map<String, String> typeMap = typeVOS.stream().collect(Collectors.toMap(typeVO -> StringUtil.cleanChars(typeVO.getName()), BulletinTypeVO::getCode));
                List<BulletinValue> valueList = newBulletinService.getInitByYear(year, id);
                Org org = orgNameMap.get(bulletinTransferVO.getOrgName());

                NewBulletin newBulletin = newBulletinWrapper.transferToEntity(bulletinTransferVO);
                List<PageData> parentList = new ArrayList<>();
                orgzationService.getParentList(org.getParentId(), parentList);
                int summaryCode = parentList.size();
                if ("6".equals(newBulletin.getTableTypeCode())){
                    summaryCode = summaryCode - 1;
                }
                newBulletin.setSummaryCode(String.valueOf(summaryCode));

                String bulletinKey =  DateUtil.format(bulletinTransferVO.getReportTime(), DateUtil.PATTERN_MONTH)
                        + StringPool.UNDERSCORE + newBulletin.getSummaryCode()
                        + StringPool.UNDERSCORE + org.getId();
                NewBulletin oldBulletin = null;
                if (oldBulletinMap.containsKey(bulletinKey)){
                    oldBulletin = oldBulletinMap.get(bulletinKey);
                    valueList = bulletinValueService.list(new LambdaQueryWrapper<BulletinValue>()
                            .eq(BulletinValue::getBulletinId, oldBulletin.getId()));
                    oldBulletin.setBulletinValues(valueList);
                    id = oldBulletin.getId();
                }

                newBulletin.setOrgId(org.getId());
                newBulletin.setDataSource(tokenUserId);
                newBulletin.setStatus("" + FINISH);
                newBulletin.setReportTime(DateUtil.parse(DateUtil.format(bulletinTransferVO.getReportTime(), DateUtil.PATTERN_MONTH) + "-01", DateUtil.PATTERN_DATE));
                newBulletin.setFormType(String.valueOf(FR_BULLETIN));
                newBulletin.setId(id);

                if (CollectionUtil.isNotEmpty(bulletinTransferVO.getBulletinValues())){
                    Map<String, BulletinValue> valueCodeMap = valueList.stream().collect(Collectors.toMap(BulletinValue::getTypeCode, value -> value));

                    for (BulletinValue bulletinValue : bulletinTransferVO.getBulletinValues()){
                        bulletinValue.setBulletinId(id);
                        if (typeMap.containsKey(StringUtil.cleanChars(bulletinValue.getTypeName()))){
                            BulletinValue value = valueCodeMap.get(typeMap.get(StringUtil.cleanChars(bulletinValue.getTypeName())));
                            bulletinValue.setId(value.getId());
                            bulletinValue.setTypeCode(value.getTypeCode());
                            bulletinValue.setTypeName(value.getTypeName());
                            bulletinValue.setColumnName(value.getColumnName());
                            bulletinValue.setSortCode(value.getSortCode());
                            bulletinValue.setDisabled(value.getDisabled());
                        }
                    }
                }
                newBulletin.setBulletinValues(bulletinTransferVO.getBulletinValues());

                result = newBulletinService.saveOrUpdate(newBulletin);
                bulletinValueService.remove(new LambdaQueryWrapper<BulletinValue>().eq(BulletinValue::getBulletinId, newBulletin.getId()));
                bulletinValueService.saveOrUpdateBatch(newBulletin.getBulletinValues());
                List<NewBulletin> list = new ArrayList<>();
                list.add(oldBulletin);
                list.add(newBulletin);
                applicationContext.publishEvent(new NewBulletinEvent(list));
            }
        }catch (Exception e){
            log.error(ExceptionUtils.getFullStackTrace(e));
        }

        return result;
    }
}
